package 线程通讯;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 【专题】多线程之间的通讯
 * <p>
 * [一]Condition
 * 1.Condition condition = lock.newCondition()
 * 2.await()休眠、signal()唤醒、signalAll()
 * <p>
 * Created by huangyu on 2018/9/1 8:38
 */
class Res02 {
	public String userSex;
	public String userName;
	public Boolean flag = false;// 线程通讯标识
	Lock lock = new ReentrantLock();
}

class Producer02 extends Thread {
	private Res02 res;
	Condition condition;

	public Producer02(Res02 res, Condition condition) {
		this.res = res;
		this.condition = condition;
	}

	@Override
	public void run() {
		int count = 0;
		while (true) {

			try {
				res.lock.lock();
				if (!res.flag) {
					try {
						condition.await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

				// flag为true时生产者进行写
				if (count == 0) {
					res.userName = "黄宇";
					res.userSex = "男";
				} else {
					res.userName = "小红";
					res.userSex = "女";
				}
				count = (count + 1) % 2;
				// 生产者写完过后,signal方法通知给消费者进行读的操作
				res.flag = false;
				condition.signal();

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				res.lock.unlock();
			}

		}
	}
}

class Comsumer02 extends Thread {
	private Res02 res;
	Condition condition;

	public Comsumer02(Res02 res, Condition condition) {
		this.res = res;
		this.condition = condition;
	}

	@Override
	public void run() {
		while (true) {

			try {
				res.lock.lock();
				if (!res.flag) {
					System.out.println(res.userName + "--" + res.userSex);
					condition.signal();
				}

				// flag为true时消费者进行等待
				res.flag = true;
				try {
					condition.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				res.lock.unlock();
			}

		}
	}
}

public class LockDemo {
	public static void main(String[] args) {
		Res02 res = new Res02();
		Condition condition = res.lock.newCondition();
		Producer02 producer = new Producer02(res, condition);
		Comsumer02 comsumer = new Comsumer02(res, condition);
		producer.start();
		comsumer.start();
	}
}
